package org.Yiran.timetale_re.block.decorate.longtable;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.ItemParticleOption;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.network.PacketDistributor;
import org.Yiran.timetale_re.capability.RuneCraftingProficiencyProvider;
import org.Yiran.timetale_re.item.ItemsRegister;
import org.Yiran.timetale_re.item.rune.base.RuneItem;
import org.Yiran.timetale_re.item.runeblueprint.base.RuneBlueprintItem;
import org.Yiran.timetale_re.network.NetworkChannel;
import org.Yiran.timetale_re.network.SCResponsePacket;
import org.Yiran.timetale_re.tile.blocktile.LongTableBlockEntity;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 长桌雕刻处理器类
 * 处理在长桌上使用凿子雕刻符文的逻辑，包括开始雕刻、继续雕刻和完成雕刻的完整流程
 * <p>
 * 主要功能:
 * 1. 处理玩家使用凿子在长桌上雕刻符文的完整流程
 * 2. 管理雕刻进度、成功率和熟练度系统
 * 3. 处理雕刻过程中的粒子效果和网络同步
 * 4. 管理玩家冷却时间和雕刻锁定机制
 */
public class LongTableCarvingHandler {

    // ==================== 常量定义 ====================

    /** 雕刻操作冷却时间（游戏刻） */
    private static final int CARVING_COOLDOWN = 5;

    /** 玩家雕刻冷却时间映射表 */
    private static final Map<UUID, Long> playerCarvingCooldown = new HashMap<>();

    /** 雕刻锁定映射表，防止多个玩家同时雕刻同一个符文 */
    private static final Map<BlockPos, UUID> carvingLocks = new HashMap<>();

    // ==================== 主要交互处理方法 ====================

    /**
     * 处理凿子使用的逻辑
     * 这是雕刻系统的核心入口点，负责处理玩家使用凿子在长桌上雕刻符文的完整流程
     *
     * @param state 方块状态
     * @param level 世界对象
     * @param pos 方块位置
     * @param player 玩家
     * @param hand 手部
     * @param hit 点击结果
     * @return 交互结果
     */
    public static InteractionResult handleChiselUse(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
        // 客户端直接返回成功，实际逻辑在服务端处理
        if (level.isClientSide) {
            return InteractionResult.SUCCESS;
        }

        // 检查玩家是否在冷却时间内
        if (isPlayerOnCooldown(player, level)) {
            return InteractionResult.PASS;
        }

        ItemStack chiselItem = player.getItemInHand(hand);
        LongTableBlockEntity tableEntity = getLongTableBlockEntity(state, level, pos);

        // 检查方块实体是否有效
        if (tableEntity == null) {
            return InteractionResult.PASS;
        }

        // 获取当前部件ID（左半部分或右半部分）
        int partId = getPartId(pos, getMainPos(pos, state, level), state.getValue(LongTable.FACING));

        // 检查当前物品是否为符文
        ItemStack currentItem = tableEntity.getItem(partId);
        if (!(currentItem.getItem() instanceof RuneItem)) {
            return InteractionResult.PASS;
        }

        // 检查点击位置是否有效（是否接近物品）
        if (!isHitNearItem(hit, pos, partId, state.getValue(LongTable.FACING), tableEntity, getMainPos(pos, state, level))) {
            return InteractionResult.PASS;
        }

        // 获取主方块位置用于锁定，防止多个玩家同时雕刻同一个符文
        BlockPos mainPos = getMainPos(pos, state, level);
        BlockPos lockPos = mainPos.relative(state.getValue(LongTable.FACING).getClockWise(), partId);

        // 检查是否已有其他玩家在雕刻这个符文
        if (carvingLocks.containsKey(lockPos) && !carvingLocks.get(lockPos).equals(player.getUUID())) {
            // 通知玩家有其他玩家正在雕刻
            player.displayClientMessage(
                    net.minecraft.network.chat.Component.translatable("message.timetale_re.rune_being_carved_by_other"),
                    true);
            return InteractionResult.FAIL;
        }

        // 设置雕刻锁定，确保同一时间只有一个玩家可以雕刻同一个符文
        carvingLocks.put(lockPos, player.getUUID());

        try {
            // 根据符文状态处理雕刻逻辑
            if (RuneItem.isBlankRune(currentItem) && !RuneItem.isBeingCarved(currentItem)) {
                // 处理开始雕刻逻辑
                return handleStartCarving(state, level, pos, player, hand, tableEntity, partId, currentItem);
            } else if (RuneItem.isBeingCarved(currentItem)) {
                // 处理继续雕刻逻辑
                return handleContinueCarving(state, level, pos, player, hand, tableEntity, partId, currentItem, chiselItem);
            }
        } finally {
            // 如果雕刻完成或失败，移除锁定
            if (!RuneItem.isBeingCarved(currentItem) || RuneItem.getCarvingProgress(currentItem) >= 100) {
                carvingLocks.remove(lockPos);
            }
        }

        // 如果没有处理雕刻，移除锁定
        carvingLocks.remove(lockPos);
        return InteractionResult.PASS;
    }

    // ==================== 冷却时间管理 ====================

    /**
     * 检查玩家是否在冷却时间内
     * 防止玩家过快地进行雕刻操作
     *
     * @param player 玩家
     * @param level 世界对象
     * @return 是否在冷却中
     */
    private static boolean isPlayerOnCooldown(Player player, Level level) {
        UUID playerId = player.getUUID();
        long currentTime = level.getGameTime();

        if (playerCarvingCooldown.containsKey(playerId)) {
            long cooldownEnd = playerCarvingCooldown.get(playerId);
            return currentTime < cooldownEnd;
        }
        return false;
    }

    /**
     * 清理雕刻冷却时间
     * 定期清理过期的冷却时间记录，避免内存泄漏
     *
     * @param level 世界对象
     */
    public static void cleanUpCarvingCooldowns(Level level) {
        long currentTime = level.getGameTime();
        playerCarvingCooldown.entrySet().removeIf(entry -> entry.getValue() < currentTime - 100); // 清理100 ticks前的记录
    }

    // ==================== 方块实体获取 ====================

    /**
     * 获取长桌方块实体
     * 确保获取到的是主方块的实体，因为长桌由两个方块组成
     *
     * @param state 方块状态
     * @param level 世界对象
     * @param pos 方块位置
     * @return 长桌方块实体
     */
    private static LongTableBlockEntity getLongTableBlockEntity(BlockState state, Level level, BlockPos pos) {
        BlockPos mainPos = getMainPos(pos, state, level);
        BlockEntity blockEntity = level.getBlockEntity(mainPos);
        return blockEntity instanceof LongTableBlockEntity ? (LongTableBlockEntity) blockEntity : null;
    }

    // ==================== 开始雕刻处理 ====================

    /**
     * 处理开始雕刻逻辑
     * 当玩家第一次使用凿子雕刻空白符文时调用
     *
     * @param state 方块状态
     * @param level 世界对象
     * @param pos 方块位置
     * @param player 玩家
     * @param hand 手部
     * @param tableEntity 长桌方块实体
     * @param partId 部件ID
     * @param currentItem 当前物品
     * @return 交互结果
     */
    private static InteractionResult handleStartCarving(BlockState state, Level level, BlockPos pos, Player player,
                                                        InteractionHand hand, LongTableBlockEntity tableEntity,
                                                        int partId, ItemStack currentItem) {
        System.out.println("开始雕刻符文 - 设置雕刻目标");

        // 查找相邻部分是否有符文图纸
        int otherPartId = (partId == LongTable.LEFT_PART) ? LongTable.RIGHT_PART : LongTable.LEFT_PART;
        ItemStack otherItem = tableEntity.getItem(otherPartId);

        if (!(otherItem.getItem() instanceof RuneBlueprintItem)) {
            System.out.println("未找到符文图纸");
            return InteractionResult.PASS;
        }

        // 获取符文图纸类型
        String runeType = RuneBlueprintItem.getRuneType(otherItem);
        if (runeType == null) {
            System.out.println("符文图纸类型为空");
            return InteractionResult.PASS;
        }

        // 设置雕刻目标
        RuneItem.setCarvingTarget(currentItem, runeType);
        RuneItem.setCarvingProgress(currentItem, 0);
        System.out.println("设置雕刻目标为: " + runeType);

        // 更新物品
        float rotation = tableEntity.getItemRotation(partId);
        float xOffset = tableEntity.getItemXOffset(partId);
        float zOffset = tableEntity.getItemZOffset(partId);

        tableEntity.setItem(partId, currentItem, rotation, xOffset, zOffset, true);

        // 添加粒子效果 - 在符文位置产生碎屑效果
        spawnCarvingParticles((ServerLevel) level, pos, partId, state.getValue(LongTable.FACING), tableEntity);

        // 设置玩家雕刻冷却时间
        playerCarvingCooldown.put(player.getUUID(), level.getGameTime() + CARVING_COOLDOWN);

        // 消耗凿子耐久度
        ItemStack chiselItem = player.getItemInHand(hand);
        chiselItem.hurtAndBreak(1, player, (p) -> p.broadcastBreakEvent(hand));

        // 发送更新包
        BlockPos mainPos = getMainPos(pos, state, level);
        tableEntity.setChanged();
        level.sendBlockUpdated(mainPos, state, state, Block.UPDATE_ALL);

        // 发送网络包同步客户端
        sendItemSyncPacket(level, mainPos, partId, currentItem, rotation, xOffset, zOffset);

        return InteractionResult.CONSUME;
    }

    // ==================== 继续雕刻处理 ====================

    /**
     * 处理继续雕刻逻辑
     * 当玩家继续雕刻已经设置了雕刻目标的符文时调用
     *
     * @param state 方块状态
     * @param level 世界对象
     * @param pos 方块位置
     * @param player 玩家
     * @param hand 手部
     * @param tableEntity 长桌方块实体
     * @param partId 部件ID
     * @param currentItem 当前物品
     * @param chiselItem 凿子物品
     * @return 交互结果
     */
    private static InteractionResult handleContinueCarving(BlockState state, Level level, BlockPos pos, Player player,
                                                           InteractionHand hand, LongTableBlockEntity tableEntity,
                                                           int partId, ItemStack currentItem, ItemStack chiselItem) {
        // 添加图纸验证逻辑
        int otherPartId = (partId == LongTable.LEFT_PART) ? LongTable.RIGHT_PART : LongTable.LEFT_PART;
        ItemStack otherItem = tableEntity.getItem(otherPartId);
        String carvingTarget = RuneItem.getCarvingTarget(currentItem);

        // 验证图纸是否仍然存在且类型匹配
        if (carvingTarget != null && (!(otherItem.getItem() instanceof RuneBlueprintItem) ||
                !carvingTarget.equals(RuneBlueprintItem.getRuneType(otherItem)))) {
            System.out.println("图纸已更换或移除，无法继续雕刻");
            return InteractionResult.PASS;
        }

        System.out.println("继续雕刻符文");

        // 计算雕刻进度增长值（添加玩家参数）
        double progressIncrement = calculateProgressIncrement(chiselItem, player);

        // 增加雕刻进度
        double currentProgress = RuneItem.getCarvingProgressDouble(currentItem);
        double newProgress = RuneItem.incrementCarvingProgress(currentItem, progressIncrement);
        System.out.println("雕刻进度: " + String.format("%.1f", currentProgress) + "% -> " + String.format("%.1f", newProgress) + "%");

        // 添加粒子效果 - 在每次雕刻时都产生碎屑效果
        spawnCarvingParticles((ServerLevel) level, pos, partId, state.getValue(LongTable.FACING), tableEntity);

        // 设置玩家雕刻冷却时间
        playerCarvingCooldown.put(player.getUUID(), level.getGameTime() + CARVING_COOLDOWN);

        float rotation = tableEntity.getItemRotation(partId);
        float xOffset = tableEntity.getItemXOffset(partId);
        float zOffset = tableEntity.getItemZOffset(partId);

        BlockPos mainPos = getMainPos(pos, state, level);

        // 如果进度达到100%，完成雕刻
        if (newProgress >= 100.0) {
            return handleCarvingCompletion(state, level, pos, player, hand, tableEntity, partId, currentItem,
                    rotation, xOffset, zOffset, mainPos);
        } else {
            // 更新雕刻进度
            tableEntity.setItem(partId, currentItem, rotation, xOffset, zOffset, true);

            // 发送网络包同步客户端
            sendItemSyncPacket(level, mainPos, partId, currentItem, rotation, xOffset, zOffset);

            // 消耗凿子耐久度
            chiselItem.hurtAndBreak(1, player, (p) -> p.broadcastBreakEvent(hand));

            // 发送更新包
            tableEntity.setChanged();
            level.sendBlockUpdated(mainPos, state, state, Block.UPDATE_ALL);

            return InteractionResult.CONSUME;
        }
    }

    // ==================== 雕刻完成处理 ====================

    /**
     * 处理雕刻完成逻辑
     * 当符文雕刻进度达到100%时调用，决定制作成功或失败
     *
     * @param state 方块状态
     * @param level 世界对象
     * @param pos 方块位置
     * @param player 玩家
     * @param hand 手部
     * @param tableEntity 长桌方块实体
     * @param partId 部件ID
     * @param currentItem 当前物品
     * @param rotation 旋转角度
     * @param xOffset X偏移
     * @param zOffset Z偏移
     * @param mainPos 主方块位置
     * @return 交互结果
     */
    private static InteractionResult handleCarvingCompletion(BlockState state, Level level, BlockPos pos, Player player,
                                                             InteractionHand hand, LongTableBlockEntity tableEntity,
                                                             int partId, ItemStack currentItem, float rotation,
                                                             float xOffset, float zOffset, BlockPos mainPos) {
        String targetType = RuneItem.getCarvingTarget(currentItem);
        System.out.println("雕刻完成，转换为: " + targetType + " 符文");

        // 获取玩家制符熟练度
        AtomicInteger playerProficiencyLevel = new AtomicInteger();
        player.getCapability(RuneCraftingProficiencyProvider.RUNE_CRAFTING_PROFICIENCY)
                .ifPresent(proficiency -> playerProficiencyLevel.set(proficiency.getProficiencyLevel()));

        // 获取目标符文等级（从图纸中获取）
        int runeLevel = 1;
        int otherPartId = (partId == LongTable.LEFT_PART) ? LongTable.RIGHT_PART : LongTable.LEFT_PART;
        ItemStack blueprintItem = tableEntity.getItem(otherPartId);
        if (blueprintItem.getItem() instanceof RuneBlueprintItem) {
            // 可以根据图纸类型或其他机制设置符文等级
            runeLevel = getRuneLevelFromBlueprint(blueprintItem);
        }

        // 计算成功率
        double successRate = calculateSuccessRate(runeLevel, playerProficiencyLevel.get());

        // 判定是否制作成功
        boolean isSuccess = level.random.nextDouble() < successRate;

        if (isSuccess) {
            System.out.println("符文制作成功，成功率: " + String.format("%.1f", successRate * 100) + "%");
            ItemStack finishedRune = RuneItem.finishCarving(currentItem);

            // 设置符文等级
            RuneItem.setRuneLevel(finishedRune, runeLevel);

            // 增加玩家经验（根据符文等级和成功率）
            double expGain = calculateExpGain(runeLevel, successRate);
            player.getCapability(RuneCraftingProficiencyProvider.RUNE_CRAFTING_PROFICIENCY)
                    .ifPresent(proficiency -> proficiency.addExperience(expGain));

            System.out.println("完成后的符文类型: " + RuneItem.getRuneType(finishedRune));
            System.out.println("完成后的符文是否为空白: " + RuneItem.isBlankRune(finishedRune));

            // 关键修改：使用完成后的符文替换当前物品
            tableEntity.setItem(partId, finishedRune, rotation, xOffset, zOffset, true);

            // 确保更新已发送
            tableEntity.setChanged();
            level.sendBlockUpdated(mainPos, state, state, Block.UPDATE_ALL);

            // 发送网络包同步客户端
            sendItemSyncPacket(level, mainPos, partId, finishedRune, rotation, xOffset, zOffset);

            // 消耗凿子耐久度
            ItemStack chiselItem = player.getItemInHand(hand);
            chiselItem.hurtAndBreak(1, player, (p) -> p.broadcastBreakEvent(hand));

            // 移除雕刻锁定
            BlockPos lockPos = mainPos.relative(state.getValue(LongTable.FACING).getClockWise(), partId);
            carvingLocks.remove(lockPos);

            // 显示成功消息
            if (!level.isClientSide) {
                player.displayClientMessage(
                        net.minecraft.network.chat.Component.translatable("message.timetale_re.rune_carving_success"),
                        true);
            }
        } else {
            System.out.println("符文制作失败，成功率: " + String.format("%.1f", successRate * 100) + "%");

            // 制作失败，直接删除空白符文
            tableEntity.removeItem(partId); // 直接移除物品而不是替换为破损符文

            // 仍然给予少量经验
            double expGain = runeLevel * 2;
            player.getCapability(RuneCraftingProficiencyProvider.RUNE_CRAFTING_PROFICIENCY)
                    .ifPresent(proficiency -> proficiency.addExperience(expGain));

            // 确保更新已发送
            tableEntity.setChanged();
            level.sendBlockUpdated(mainPos, state, state, Block.UPDATE_ALL);

            // 发送网络包同步客户端（发送空物品表示移除）
            NetworkChannel.CHANNEL.send(
                    PacketDistributor.TRACKING_CHUNK.with(() -> level.getChunkAt(mainPos)),
                    new SCResponsePacket.LongTableItemSyncPacket(mainPos, partId)
            );

            // 消耗凿子耐久度
            ItemStack chiselItem = player.getItemInHand(hand);
            chiselItem.hurtAndBreak(1, player, (p) -> p.broadcastBreakEvent(hand));

            // 移除雕刻锁定
            BlockPos lockPos = mainPos.relative(state.getValue(LongTable.FACING).getClockWise(), partId);
            carvingLocks.remove(lockPos);

            // 显示失败消息
            if (!level.isClientSide) {
                player.displayClientMessage(
                        net.minecraft.network.chat.Component.translatable("message.timetale_re.rune_carving_failed"),
                        true);
            }
        }

        return InteractionResult.CONSUME;
    }

    // ==================== 粒子效果处理 ====================

    /**
     * 生成雕刻粒子效果
     * 在符文位置生成碎屑粒子，增强视觉反馈
     *
     * @param level 服务端世界对象
     * @param pos 方块位置
     * @param partId 部件ID
     * @param facing 朝向
     * @param tableEntity 长桌方块实体
     */
    private static void spawnCarvingParticles(ServerLevel level, BlockPos pos, int partId, Direction facing, LongTableBlockEntity tableEntity) {
        // 计算符文的世界坐标位置
        Vec3 particlePos = LongTable.getItemRenderPosition(
                getMainPos(pos, level.getBlockState(pos), level),
                partId,
                facing,
                tableEntity
        );

        // 在符文位置生成粒子效果
        for (int i = 0; i < 3; i++) {
            // 随机偏移量，使粒子分布在符文周围
            double offsetX = (level.random.nextFloat() - 0.5) * 0.3;
            double offsetY = (level.random.nextFloat() - 0.5) * 0.3;
            double offsetZ = (level.random.nextFloat() - 0.5) * 0.3;

            // 使用 ITEM_CRACK 粒子类型，这是 Minecraft 内置的物品碎裂粒子效果
            // 粒子贴图大小会自动根据物品决定，我们通过传递空白符文物品来控制贴图
            level.sendParticles(
                    new ItemParticleOption(ParticleTypes.ITEM, new ItemStack(ItemsRegister.RUNE.get())),
                    particlePos.x + offsetX,
                    particlePos.y + 0.3 + offsetY, // 稍微抬高一点避免在地面下
                    particlePos.z + offsetZ,
                    1, // 粒子数量
                    0, 0, 0, // 速度偏移
                    0.02 // 速度倍数
            );
        }
    }

    // ==================== 进度计算方法 ====================

    /**
     * 计算雕刻进度增长值
     * 根据凿子等级、玩家状态和熟练度等因素计算进度增长
     *
     * @param chiselItem 凿子物品
     * @param player 玩家（可能坐在椅子上）
     * @return 进度增长值
     */
    private static double calculateProgressIncrement(ItemStack chiselItem, Player player) {
        double progressIncrement = 0.8; // 基础增长值

        // 如果凿子是ChiselItem类型，根据凿子等级增加进度增长
        if (chiselItem.getItem() instanceof org.Yiran.timetale_re.item.tool.chisel.base.ChiselItem chisel) {
            int chiselLevel = chisel.getChiselLevel();
            progressIncrement *= (1 + chiselLevel); // 每级增加100%的基础增长
            System.out.println("使用等级 " + chiselLevel + " 的凿子，进度增长: " + progressIncrement + "%");
        }

        // 检查玩家是否坐在椅子上，如果是则提供20%的速度加成
        if (player.isPassenger() && player.getVehicle() instanceof org.Yiran.timetale_re.entity.SitEntity) {
            progressIncrement *= 1.2; // 20%雕刻速度加成
            System.out.println("玩家坐在椅子上雕刻，获得20%速度加成，当前进度增长: " + progressIncrement + "%");
        }

        // 根据制符熟练等级提供雕刻速度加成
        AtomicInteger playerProficiencyLevel = new AtomicInteger();
        player.getCapability(RuneCraftingProficiencyProvider.RUNE_CRAFTING_PROFICIENCY)
                .ifPresent(proficiency -> playerProficiencyLevel.set(proficiency.getProficiencyLevel()));

        int proficiencyLevel = playerProficiencyLevel.get();
        // 每级制符熟练度提供3%的雕刻速度加成
        double proficiencyBonus = 1.0 + (proficiencyLevel * 0.03);
        progressIncrement *= proficiencyBonus;

        System.out.println("制符熟练度 " + proficiencyLevel + " 级，获得 " + (proficiencyLevel * 3) + "% 速度加成");

        return progressIncrement;
    }

    // ==================== 成功率和经验计算 ====================

    /**
     * 根据图纸确定符文等级
     * 从符文图纸中获取目标符文的等级
     *
     * @param blueprintItem 符文图纸物品
     * @return 符文等级
     */
    private static int getRuneLevelFromBlueprint(ItemStack blueprintItem) {
        if (blueprintItem.getItem() instanceof RuneBlueprintItem) {
            int level = RuneBlueprintItem.getRuneLevel(blueprintItem);
            return Math.max(1, Math.min(5, level));
        }
        return 1;
    }

    /**
     * 计算制作成功率
     * 根据符文等级和玩家熟练度计算制作成功率
     *
     * @param runeLevel 符文等级
     * @param playerProficiencyLevel 玩家熟练度等级
     * @return 制作成功率（0-1之间）
     */
    private static double calculateSuccessRate(int runeLevel, int playerProficiencyLevel) {
        // 不同等级的基础成功率
        double baseSuccessRate = switch (runeLevel) {
            case 1 -> 0.50;  // 50%
            case 2 -> 0.35;  // 35%
            case 3 -> 0.15;  // 15%
            case 4 -> 0.05;  // 5%
            case 5 -> 0.01;  // 1%
            default -> 0;
        };

        double proficiencyBonus = playerProficiencyLevel * 0.03;

        return Math.min(1, baseSuccessRate + proficiencyBonus);
    }

    /**
     * 计算制作成功后获得的经验值
     * 根据符文等级、成功率和随机因素计算经验奖励
     *
     * @param runeLevel 符文等级
     * @param successRate 成功率
     * @return 获得的经验值
     */
    private static double calculateExpGain(int runeLevel, double successRate) {
        // 基础经验池（等级越高经验越多）
        double baseExp = switch (runeLevel) {
            case 1 -> 10.0;
            case 2 -> 25.0;
            case 3 -> 50.0;
            case 4 -> 100.0;
            case 5 -> 200.0;
            default -> 0;
        };

        // 难度系数（成功率越低，经验奖励越高）
        double difficultyMultiplier = (1.0 - successRate) * 10; // 最多10倍经验

        // 基础经验计算
        double baseCalculatedExp = baseExp * (1 + difficultyMultiplier);

        // 添加随机性（±20%浮动）
        double randomFactor = 0.8 + (Math.random() * 0.4); // 0.8到1.2之间的随机数

        // 最终经验 = 基础经验 * 随机因子
        return baseCalculatedExp * randomFactor;
    }

    // ==================== 网络同步方法 ====================

    /**
     * 发送物品同步网络包
     * 将物品状态变化同步到客户端
     *
     * @param level 世界对象
     * @param mainPos 主方块位置
     * @param partId 部件ID
     * @param itemStack 物品堆
     * @param rotation 旋转角度
     * @param xOffset X偏移
     * @param zOffset Z偏移
     */
    private static void sendItemSyncPacket(Level level, BlockPos mainPos, int partId, ItemStack itemStack,
                                          float rotation, float xOffset, float zOffset) {
        NetworkChannel.CHANNEL.send(
                PacketDistributor.TRACKING_CHUNK.with(() -> level.getChunkAt(mainPos)),
                new SCResponsePacket.LongTableItemSyncPacket(mainPos, partId, itemStack, rotation, xOffset, zOffset, true)
        );
    }

    // ==================== 位置和部件计算 ====================

    /**
     * 检查点击位置是否在物品渲染位置附近
     * 确保玩家点击的是物品本身而不是空旷区域
     *
     * @param hit 点击结果
     * @param pos 方块位置
     * @param partId 部件ID
     * @param facing 朝向
     * @param tableEntity 长桌方块实体
     * @param mainPos 主方块位置
     * @return 是否在附近
     */
    private static boolean isHitNearItem(BlockHitResult hit, BlockPos pos, int partId, net.minecraft.core.Direction facing,
                                         LongTableBlockEntity tableEntity, BlockPos mainPos) {
        ItemStack currentItem = tableEntity.getItem(partId);

        // 如果是地图物品或符文图纸，只需点击对应桌面部分即可
        if (currentItem.getItem() instanceof net.minecraft.world.item.MapItem || currentItem.getItem() instanceof RuneBlueprintItem) {
            // 获取点击的方块位置
            BlockPos hitPos = hit.getBlockPos();
            // 检查点击位置是否为当前部分的桌面
            return hitPos.equals(pos);
        }

        // 其他物品保持原有逻辑
        // 获取点击位置
        Vec3 hitPos = hit.getLocation();

        // 计算物品渲染位置 - 使用mainPos来正确计算右半部分物品位置
        Vec3 itemRenderPos = LongTable.getItemRenderPosition(mainPos, partId, facing, tableEntity);

        // 计算点击位置与物品渲染位置的距离
        double distance = hitPos.distanceTo(itemRenderPos);

        // 如果距离小于0.3，则认为点击位置接近物品
        return distance < 0.3;
    }

    /**
     * 获取主方块位置（左半部分）
     * 确保总是获取到长桌的主方块位置
     *
     * @param pos 当前位置
     * @param state 方块状态
     * @param level 世界对象
     * @return 主方块位置
     */
    private static BlockPos getMainPos(BlockPos pos, BlockState state, Level level) {
        return LongTable.getMainPos(pos, state);
    }

    /**
     * 根据当前位置和主位置计算部件ID
     * 确定当前操作的是长桌的左半部分还是右半部分
     *
     * @param pos 当前位置
     * @param mainPos 主位置
     * @param facing 朝向
     * @return 部件ID
     */
    private static int getPartId(BlockPos pos, BlockPos mainPos, net.minecraft.core.Direction facing) {
        if (pos.equals(mainPos)) {
            return LongTable.LEFT_PART;
        } else {
            return LongTable.RIGHT_PART;
        }
    }
}